home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
bode.arc
/
BODE.PAS
Wrap
Pascal/Delphi Source File
|
1985-09-23
|
8KB
|
213 lines
PROGRAM BODE ;
{ Program to calculate the frequency response plot (bode diagram)
for a transfer function provided to the program in terms of
numerator and denominator polynominal coefficients of the
Laplace transfer function. The order of the polynominals must
be less than or equal to 20.
First revision completed by Mike Secord on 10/23/84
The program was written to try to optimize the execution speed.
Second revision -- fix bugs 11/15/84
Revision 2.1 -- display program description when executed 8/34/85 }
CONST
VERSION='VERSION 2.1' ;
MAXSTEPS=100;
NATLOG=2.302585093;
TYPE
NUMFREQ=ARRAY[1..MAXSTEPS] OF REAL;
COEF_ARRAY = ARRAY [0..20] OF REAL ;
NAME = ARRAY [1..11] OF CHAR ;
VAR FREQVAL:NUMFREQ;
NSTEP,I:INTEGER;
M : INTEGER ; { ORDER OF NUMERATOR POLYNOMIAL }
N : INTEGER ; { ORDER OF DENOMINATOR POLYNOMIAL}
PN : COEF_ARRAY ; { ARRAY OF NUMERATOR POLYNOMIAL COEFFICIENTS }
PD : COEF_ARRAY ; { ARRAY OF DENOMINATOR POLYNOMIAL COEFFICIENTS }
INTYPE : NAME ; { NAME FOR TYPE OF INPUT (DENOM OR NUM) }
KGAIN, W, MAGN, MAGD, PHASEN, PHASED, MAGNITUDE, LOGMAG, PHASE : REAL ;
ANS : CHAR ;
PROCEDURE TRANFUNC(INTYPE :NAME ; VAR O : INTEGER; VAR C : COEF_ARRAY) ;
{procedure to input the transfer function (pole and zero) information
for the BODE program.}
VAR
L : INTEGER ;
BEGIN
WRITELN ;
WRITE(' Enter the order of the ',INTYPE,' polynomial (20 Max) : ') ;
READLN(O) ;
WRITELN ;
WRITELN(' Enter the coefficients of the ',INTYPE,' polynomial in ') ;
WRITELN(' desending order (PLEASE ENTER ZERO COEFFICIENTS ALSO). ') ;
WRITELN(' ',INTYPE,' coefficients : ') ;
FOR L := O DOWNTO 0 DO
BEGIN
WRITE(' S',L,': ') ;
READ(C[L]) ;
IF( (O-L) MOD 4 = 0) AND (L <> O) THEN WRITELN ;
END ;
WRITELN ; WRITELN ;
END ;
PROCEDURE CALCFREQ(VAR FREQ:NUMFREQ;VAR V:INTEGER);
{calculate series of frequencies to be used for bode plot}
VAR INITIALFREQ:REAL;
FINALFREQ:REAL;
LOGDECADE_STEP:INTEGER;
STARTFREQ:REAL;
ENDFREQ:REAL;
TRUNCFREQ:INTEGER;
DIFF:REAL;
LOGSTEP:REAL;
LOGFREQ:REAL;
BEGIN {input initial frequency,final frequency,and number of steps per decade}
WRITELN ;
WRITE(' Type initial frequency desired in output: ');
READLN(INITIALFREQ);
INITIALFREQ := INITIALFREQ - INITIALFREQ/1000.0 ; {Allow for trunc}
WRITE(' Type final frequency desired in output: ');
READLN(FINALFREQ);
FINALFREQ := FINALFREQ + FINALFREQ/1000.0 ; {Allow for truncation}
WRITE(' Type no. of log steps desired for each decade of output: ');
READLN(LOGDECADE_STEP);
{calculate log of input frequencies and frequency steps}
STARTFREQ:=(1/NATLOG)*LN(INITIALFREQ);
ENDFREQ:=(1/NATLOG)*LN(FINALFREQ);
TRUNCFREQ:=TRUNC(STARTFREQ);
DIFF:=STARTFREQ-TRUNCFREQ;
LOGSTEP:=1/LOGDECADE_STEP;
LOGFREQ:=((TRUNC(DIFF/LOGSTEP))/LOGDECADE_STEP)+TRUNCFREQ;
V:=0;
{calculate series of frequencies and put into array}
WHILE LOGFREQ<=ENDFREQ DO
BEGIN
V:=V+1;
FREQ[V]:=EXP(NATLOG*LOGFREQ);
LOGFREQ:=LOGFREQ+LOGSTEP;
END;
END;
PROCEDURE CALC(ORDER : INTEGER; C : COEF_ARRAY; VAR MAG, ANGLE : REAL;
W : REAL) ;
{ Procedure to calculate the magnitude and phase response for the numerator
or denominator as called. The total response will be calculated in the
main body of the program. }
FUNCTION CMULT(W,K : REAL; EXPON : INTEGER) : REAL ;
{ This function calculates the w terms to the respective powers as called
and was faster than using EXP(U*LN(A)).}
VAR
P : INTEGER ;
TEMP2, MPLICND : REAL ;
BEGIN
MPLICND := W ; TEMP2 := W ;
CASE EXPON OF
0 : CMULT := K ;
1 : CMULT := W*K ;
2..20 : BEGIN { 20 needs to be changed for more than 20th order}
FOR P := 2 TO EXPON DO TEMP2 := TEMP2*MPLICND ;
CMULT := K*TEMP2 ;
END ;
END ; {case}
END ; {function CMULT }
VAR
TEMP, RCMULT, ICMULT : REAL ;
I1 : INTEGER ;
BEGIN
RCMULT := 0.0 ; ICMULT := 0.0 ;
FOR I1 := 0 TO ORDER DO
BEGIN
{ NOTE: These sets for the case statement have to be added to
in increments of 4 if the procedure is
to calculate the response of a polynominal > 20. }
CASE I1 OF
0,4,8,12,16,20 : RCMULT := RCMULT + CMULT(W,C[I1],I1) ;
1,5,9,13,17 : ICMULT := ICMULT + CMULT(W,C[I1],I1) ;
2,6,10,14,18 : RCMULT := RCMULT - CMULT(W,C[I1],I1) ;
3,7,11,15,19 : ICMULT := ICMULT - CMULT(W,C[I1],I1) ;
END ; {case}
END ; {for}
MAG := SQRT(RCMULT*RCMULT + ICMULT*ICMULT) ;
IF (RCMULT = 0.0) AND (ICMULT > 0.0) THEN ANGLE := PI/2.0 ;
IF (RCMULT = 0.0) AND (ICMULT < 0.0) THEN ANGLE := -PI/2.0 ;
IF (ICMULT = 0.0) AND (RCMULT < 0.0) THEN ANGLE := PI ;
IF RCMULT > 0.0 THEN ANGLE := ARCTAN(ICMULT/RCMULT) ;
IF (RCMULT < 0.0) AND (ICMULT > 0.0) THEN
ANGLE := ARCTAN(ICMULT/RCMULT) + PI ;
IF (RCMULT < 0.0) AND (ICMULT < 0.0) THEN
ANGLE := ARCTAN(ICMULT/RCMULT) - PI ;
END ; { procedure ccalc }
{*************** MAIN PROGRAM ****************************************}
BEGIN
CLRSCR ;
GOTOXY(15,8) ;
WRITE('********** PROGRAM BODE **********') ;
GOTOXY(26,9) ;
WRITE(VERSION) ;
GOTOXY(1,11) ;
WRITELN(' Program to calculate the frequency response plot (Bode diagram)');
WRITELN(' for a transfer function provided to the program in terms of');
WRITELN(' numerator and denominator polynominal coefficients of the');
WRITELN(' Laplace transfer function. The order of the polynominals must');
WRITELN(' be less than or equal to 20.');
WRITELN ;
WRITELN(' Enter data when prompted (Do NOT forget the zero coefficients)');
WRITELN ; WRITELN ;
INTYPE := ' numerator ' ;
TRANFUNC(INTYPE,M,PN) ;
INTYPE :='denominator' ;
TRANFUNC(INTYPE,N,PD) ;
WRITELN ;
WRITE(' Enter the gain coefficient (Enter 1 if there is none) : ') ;
READLN(KGAIN) ;
CALCFREQ(FREQVAL,NSTEP);
WRITELN ; WRITELN ;
WRITELN(' FREQUENCY MAGNITUDE MAGNITUDE DB PHASE DEG ') ;
WRITELN ;
FOR I:= 1 TO NSTEP DO
BEGIN
W := FREQVAL[I]*2.0*PI ;
CALC(M,PN,MAGN,PHASEN,W) ; {Calculate the numerator respsonse}
CALC(N,PD,MAGD,PHASED,W) ; {Calculate the denominator response}
MAGNITUDE := KGAIN* MAGN/MAGD ;
LOGMAG := (20.0/NATLOG)*LN(MAGNITUDE) ; {Magnitude in DB}
PHASE :=(PHASEN - PHASED)*180.0/PI ; {Phase in degrees}
WRITELN(' ',FREQVAL[I]:12,' ',MAGNITUDE:12,' ',LOGMAG:12,
' ',PHASE:12);
END;
{Part of program to print to printer on request}
WRITELN;
WRITE(' Would you like the output directed to the printer (Y or N) : ') ;
READLN(ANS) ;
IF ANS ='Y' THEN
BEGIN
WRITELN(LST) ; WRITELN(LST) ;
WRITELN(LST,' FREQUENCY MAGNITUDE MAGNITUDE DB PHASE DEG ');
WRITELN(LST) ;
FOR I:= 1 TO NSTEP DO
BEGIN
W := FREQVAL[I]*2.0*PI ;
CALC(M,PN,MAGN,PHASEN,W) ; {Calculate the numerator respsonse}
CALC(N,PD,MAGD,PHASED,W) ; {Calculate the denominator response}
MAGNITUDE := KGAIN* MAGN/MAGD ;
LOGMAG := (20.0/NATLOG)*LN(MAGNITUDE) ; {Magnitude in DB}
PHASE :=(PHASEN - PHASED)*180.0/PI ; {Phase in degrees}
WRITELN(LST,FREQVAL[I]:12,' ',MAGNITUDE:12,' ',LOGMAG:12,
' ',PHASE:12);
END; {FOR}
END ; {END PRINTER IF}
END. {BODE}